using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using memdb_demo.Interop.WrapModels;
using memdb_demo.Utils.Exceptions;

namespace memdb_demo.Interop{
    public class OrderQueryWrapper{


#region externs
        private const string DLL_FILE = "CPPDLL.so";
        /// <summary>
        /// 创建报单监控查询条件对象
        /// </summary>
        /// <param name="offset">偏移量，从第几条开始查询</param>
        /// <param name="size">查询量，需要查询几条数据</param>
        /// <returns></returns>
        [DllImport(DLL_FILE,EntryPoint= "orderQueryCreateOption",CallingConvention =CallingConvention.Cdecl)]
        private extern static IntPtr _orderQueryCreateOption(uint offset,uint size);


        /// <summary>
        /// 释放报单监控查询条件对象
        /// </summary>
        /// <param name="handle"></param>
        [DllImport(DLL_FILE,EntryPoint= "orderQueryDestroyOption",CallingConvention =CallingConvention.Cdecl)]
        private extern static void _orderQueryDestroyOption(IntPtr handle);


        /// <summary>
        /// 设置报单查询条件对象Offset属性
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="handle"></param>
        [DllImport(DLL_FILE,EntryPoint= "orderQueryOptionSetOffset",CallingConvention =CallingConvention.Cdecl)]
        private extern static void _orderQueryOptionSetOffset(uint offset,IntPtr handle);


        /// <summary>
        /// 设置报单查询条件对象Size属性
        /// </summary>
        /// <param name="size"></param>
        /// <param name="handle"></param>
        [DllImport(DLL_FILE,EntryPoint= "orderQueryOptionSetSize",CallingConvention =CallingConvention.Cdecl)]
        private extern static void _orderQueryOptionSetSize(uint size,IntPtr handle);


        /// <summary>
        /// 创建报单查询结果对象
        /// </summary>
        /// <param name="count">请求查询结果记录条数</param>
        /// <returns></returns>
        [DllImport(DLL_FILE,EntryPoint= "orderQueryCreateData",CallingConvention =CallingConvention.Cdecl)]
        private extern static IntPtr _orderQueryCreateData(uint count);

        /// <summary>
        /// 创建报单查询结果对象
        /// </summary>
        /// <param name="handle">查询结果对象句柄</param>
        /// <returns></returns>
        [DllImport(DLL_FILE,EntryPoint= "orderQueryDestoryData",CallingConvention =CallingConvention.Cdecl)]
        private extern static void _orderQueryDestroyData(IntPtr handle);

        /// <summary>
        /// 获取报单查询结果错误明细信息
        /// </summary>
        /// <param name="handle">查询结果对象句柄</param>
        /// <returns></returns>
        [DllImport(DLL_FILE,EntryPoint= "orderQuerygetResultMsg",CallingConvention =CallingConvention.Cdecl)]
        private extern static StringBuilder _orderQuerygetResultMsg(IntPtr handle);


        /// <summary>
        /// 获取报单查询结果总数量
        /// </summary>
        /// <param name="handle">查询结果对象句柄</param>
        /// <returns></returns>
        [DllImport(DLL_FILE,EntryPoint= "orderQuerygetTotalCnt",CallingConvention =CallingConvention.Cdecl)]
        private extern static long _orderQuerygetTotalCnt(IntPtr handle);


        /// <summary>
        /// 获取报单查询结果的实际数量
        /// </summary>
        /// <param name="handle">查询结果对象句柄</param>
        /// <returns></returns>
        [DllImport(DLL_FILE,EntryPoint= "orderQuerygetCurrentCnt",CallingConvention =CallingConvention.Cdecl)]
        private extern static long _orderQuerygetCurrentCnt(IntPtr handle);


        /// <summary>
        /// 获取报单查询结果集合
        /// </summary>
        /// <param name="handle">查询结果对象句柄</param>
        /// <returns></returns>
        [DllImport(DLL_FILE,EntryPoint= "orderQueryDataCollection",CallingConvention =CallingConvention.Cdecl)]
        private extern static IntPtr _orderQueryDataCollection(IntPtr handle);


        /// <summary>
        /// 查询报单监控数据
        /// </summary>
        /// <param name="orderQueryOptionHandle">报单监控查询条件对象句柄</param>
        /// <param name="orderQueryDataHandle">报单监控查询结果对象句柄</param>
        /// <returns></returns>
        [DllImport(DLL_FILE,EntryPoint= "orderQuery",CallingConvention =CallingConvention.Cdecl)]
        private extern static int _orderQuery(IntPtr orderQueryOptionHandle,IntPtr orderQueryDataHandle);

#endregion externs

        public  IntPtr CreateOrderQueryOption(uint offset,uint size){
            var handle = _orderQueryCreateOption(offset,size);
            if (IntPtr.Zero == handle){
                throw new InterfaceWrapperException($"call _orderQueryCreateOption failed: handle returned zero with offset:{offset},size:{size}");
            }
            return handle;
        }

        internal IntPtr CreateOrderQueryData(uint count){
            var handle = _orderQueryCreateData(count);
            if (IntPtr.Zero == handle){
                throw new InterfaceWrapperException($"call _orderQueryCreateData failed: handle returned zero with count:{count}");
            }
            return handle;
        }

        internal int ExcuteOrderQuery(IntPtr optionHandle, IntPtr dataHandle)
        {
            var rtn = _orderQuery(optionHandle,dataHandle);
            return rtn;
        }


        internal long GetOrderQueryDataCurrentCount(IntPtr dataHandle)
        {
            var currentcount = _orderQuerygetCurrentCnt(dataHandle);
            return currentcount;
        }

        internal IntPtr GetOrderQueryDataCollection(IntPtr dataHandle)
        {
            var handle = _orderQueryDataCollection(dataHandle);
            if (IntPtr.Zero == handle){
                throw new InterfaceWrapperException($"call _orderQueryDataCollection failed: handle returned zero with dataHandle:{dataHandle}");
            }
            return handle;
        }



        internal IList<Record<Order>> Deserialize(IntPtr resultHandle,int count)
        {
            var result = new List<Record<Order>>(count);
            var pCurrentOrder = resultHandle;
            for(var i =0;i<count;i++){
                var order = Marshal.PtrToStructure<Order>(pCurrentOrder);
                result.Add(new Record<Order>{Value=order});
                pCurrentOrder += Marshal.SizeOf<Order>();
            }
            return result;
        }


        internal void DestroyOption(IntPtr handle){
            _orderQueryDestroyOption(handle);
        }

        internal void DestroyData(IntPtr handle){
            _orderQueryDestroyData(handle);
        }

       

    }

}

